﻿#ifndef GLOBAL_H
#define GLOBAL_H
#include <vector>
#include <QDebug>

//#define NDEBUG   // debug模式

extern const float STEP;


typedef struct Point {

    Point():x(0), y(0), z(0) {}
    Point(double x, double y, double z) : x(x), y(y), z(z) {}

    double x;
    double y;
    double z;

}Point;



typedef struct Triangle {

    Point normal;       /// 法向量

    std::vector<Point> vertexs;     /// 顶点坐标

}Triangle;



/// xyz轴
typedef enum Axis {

    X,
    Y,
    Z,
    NONE

}Axis;



/** xyz轴所对应的旋转环 */
typedef enum Circle {

    CIRCLE_X,   /// 控制绕x轴旋转
    CIRCLE_Y,
    CIRCLE_Z,
    EMPTY

}Circle;



/** 关节类型 */
typedef enum JointType {

    BASE,   /// 基座
    J1,     /// 关节一
    J2,
    J3,
    J4,
    J5,
    J6

}JointType;



/** 储存各关节弧度的结构体 */
typedef struct Joint {

    Joint() : j1(0), j2(0), j3(0), j4(0), j5(0), j6(0) {}

    Joint(double j1, double j2, double j3, double j4, double j5, double j6) : j1(j1), j2(j2), j3(j3), j4(j4), j5(j5), j6(j6) {}

    Joint(const Joint& joint)
    {
        j1 = joint.j1;
        j2 = joint.j2;
        j3 = joint.j3;
        j4 = joint.j4;
        j5 = joint.j5;
        j6 = joint.j6;
    }

    Joint& operator=(const Joint& joint)
    {
        j1 = joint.j1;
        j2 = joint.j2;
        j3 = joint.j3;
        j4 = joint.j4;
        j5 = joint.j5;
        j6 = joint.j6;
        return *this;
    }

    void print() const
    {

        qDebug() << QString("[%1, %2, %3, %4, %5, %6]").arg(j1).arg(j2).arg(j3).arg(j4).arg(j5).arg(j6);

    }


    double j1 = 0;      /// 单位角度
    double j2 = 0;
    double j3 = 0;
    double j4 = 0;
    double j5 = 0;
    double j6 = 0;

}Joint;

extern Joint lastJoint;

/** 储存关节旋转信息 */
typedef struct RotateInfo {

    JointType joint;
    double angle;

}RotateInfo;


/** 载入关节的信息: 关节地址和关节名称 */
#include <osg/Node>
typedef struct NodeInfo {

    osg::ref_ptr<osg::Node> pNode;
    QString name;
    JointType jointType;

}NodeInfo;



/** 轨迹线类型 */
typedef enum PathElementType {

    MoveJ,       /// 空移线
    MoveLine,    /// 直线
    MoveArc,     /// 圆弧
    ERR

} PathElementType;



#include <osg/NodeVisitor>                  /// osg::NodeVisitor
#include <osg/MatrixTransform>              /// osg::Transform
#include <QDebug>


/** 定义遍历搜索指定名称关节的迭代器 */
class FindNodeWithName : public osg::NodeVisitor
{

    private:

        FindNodeWithName() = default;

    public:
        /** 构造传入要搜索节点的名字 */
        FindNodeWithName(std::string name) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), targetName(name), targetNode(nullptr) { }

        /** 递归的遍历整颗树 直到找到目标节点结束递归*/
        inline virtual void apply(osg::Node& node)
        {

            if (node.getName() == targetName) {
                targetNode = &node;
                return;
            }

            traverse(node);

        }

        /** 返回找到的节点地址 */
        inline osg::ref_ptr<osg::Node> getNode()
        {

            return targetNode;

        }

    private:

        std::string targetName;             /// 目标名称

        osg::ref_ptr<osg::Node> targetNode; /// 目标节点地址

};



/** 定义遍历搜索指定旋转节点的迭代器 */
class MTNodeVistor : public osg::NodeVisitor
{

    private:

        MTNodeVistor() = default;

    public:
        /** 构造传入要搜索的第index旋转节点 */
        MTNodeVistor(const int index) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), targetIndex(index), curIndex(0), targetMatrixTransform(nullptr){}

        /** 递归的遍历整颗树 直到第n个旋转节点结束递归*/
        virtual void apply(osg::MatrixTransform& mt)
        {

            if (curIndex == targetIndex) {
                targetMatrixTransform = &mt;
                return;
            }

            curIndex++;
            traverse(mt);

        }

        osg::MatrixTransform* getMTNode()
        {

            return targetMatrixTransform;

        }

    private:

        int curIndex;

        int targetIndex;

        osg::MatrixTransform* targetMatrixTransform;

};





#endif // GLOBAL_H
